import json
import re

from django.contrib.auth import login, logout
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render, redirect
from django.http import HttpResponseForbidden,HttpResponse,JsonResponse,HttpResponseBadRequest,HttpResponseServerError

from apps.areas.models import Area
from utils.response_code import RETCODE
from django.urls import reverse
from django.views import View

from apps.users.models import User
from meiduo_mall.settings.dev import logger

#10.省市区查询
class AreasView(LoginRequiredMixin,View):
    def get(self,request):
        area_id = request.GET.get('area_id')

        #如果area_id不存在则表示查询省份
        if not area_id:
            try:
                province_model_list = Area.objects.filter(parent__isnull=True)
                #序列化
                province_list = []
                for province_model in province_model_list:
                    province_list.append({'id':province_model.id,'name':province_model.name})
            except Exception as e:
                logger.error(e)
                return JsonResponse({'code':RETCODE.DBERR,'errmsg':'省份数据错误'})
            return JsonResponse({'code':RETCODE.OK,'errmsg':'OK','province_list':province_list})
        else:
            try:
                parent_model = Area.objects.get(id=area_id)  # 查询市或区的父级
                sub_model_list = parent_model.subs.all()
                # subs = Area.objects.filter(parent=area_id)
                # print(subs)


                # 序列化市或区数据
                sub_list = []
                for sub_model in sub_model_list:
                    sub_list.append({'id': sub_model.id, 'name': sub_model.name})

                sub_data = {
                    'id': parent_model.id,  # 父级pk
                    'name': parent_model.name,  # 父级name
                    'subs': sub_list  # 父级的子集
                }
            except Exception as e:
                logger.error(e)
                return JsonResponse({'code': RETCODE.DBERR, 'errmsg': '城市或区数据错误'})

                # 响应市或区数据
            return JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'sub_data': sub_data})

#9.收货地址
class AddressView(LoginRequiredMixin,View):
    def get(self,request):
        return render(request,"user_center_site.html")

#8.邮箱验证
class VerifyEmailView(View):
    def get(self,request):
        secret_token = request.GET.get('token')

        #校验token
        if not secret_token:
            return HttpResponseBadRequest("缺少token参数")
        #对token进行校验
        from apps.users.utils import check_email_token
        user = check_email_token(secret_token)
        if not user:
            return HttpResponseForbidden('无效的token')

        try:
            user.email_active = True
            user.save()
        except Exception as e:
            logger.error(e)
            return HttpResponseServerError('激活邮箱失败')

        return redirect(reverse("users:info"))

#7.添加邮箱
class EmailView(LoginRequiredMixin,View):
    def put(self,request):
        #接受参数
        json_str = request.body.decode()
        json_dict = json.loads(json_str)
        email = json_dict['email']
        print(email)

        #校验参数
        if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$',email):
            return HttpResponseForbidden("参数email有误")
        #将email保存到数据库中
        try:
            request.user.email = email
            request.user.save()
        except Exception as e:
            logger.error(e)
            return JsonResponse({'code':RETCODE.DBERR,'errmsg':'添加邮箱失败'})

        #异步发送邮件
        from apps.users.utils import generate_verify_email_url
        from celery_tasks.email.tasks import send_verify_email
        send_verify_email.delay(email,generate_verify_email_url(request.user))
        #返回响应结果
        return JsonResponse({'code': RETCODE.OK, 'errmsg': '添加邮箱成功'})

#6.展示用户首页
class UserInfoView(LoginRequiredMixin,View):
    def get(self,request):
        context = {
            'username':request.user.username,
            'mobile':request.user.mobile,
            'email':request.user.email,
            'email_active':request.user.email_active
        }
        return render(request,'user_center_info.html',context=context)

#5.退出功能
class LogoutView(View):
    def get(self,request):
        logout(request)
        response = redirect(reverse('users:login'))
        response.delete_cookie('username')
        return response

#4.登录功能
class LoginView(View):
    def get(self,request):
        return render(request,"login.html")

    def post(self,request):
        #1.接收参数
        username = request.POST.get('username')
        password = request.POST.get('password')
        remembered = request.POST.get('remembered')

        #2.校验参数
        if not all([username,password]):
            return HttpResponseForbidden('参数不齐全')

        # 2.1 用户名
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return HttpResponseForbidden('请输入5-20个字符的用户名')
        # 2.2 密码
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return HttpResponseForbidden('请输入8-20位的密码')

        from django.contrib.auth import authenticate,login
        user = authenticate(username = username, password = password)

        if user is None:
            return render(request,'login.html',{'account_errmsg': '用户名或密码错误'})
        login(request,user)

        if remembered != 'on':
            request.session.set_expiry(0)
        else:
            request.session.set_expiry(None)
        next = request.GET.get('next')
        if next:
            response = redirect(next)
        else:
            response = redirect(reverse('contents:index'))
        # response = redirect(reverse('contents:index'))
        response.set_cookie('username',request.user.username,max_age=60)
        return response


# 3.手机号重复
class MobileCountView(View):
    def get(self,request,mobile):
        count = User.objects.filter(mobile=mobile).count()
        return JsonResponse({"code":RETCODE.OK,"errmsg":"OK","count":count})


# 2.用户名重复
class UsernameCountView(View):
    def get(self,request,username):
        count = User.objects.filter(username=username).count()

        return JsonResponse({"code":RETCODE.OK,"errmsg":"OK","count":count})


# 1.注册后端逻辑
class RegisterView(View):
    # get方式获取注册界面
    def get(self,request):
        return render(request,"register.html")

    # post方式提交数据进行逻辑处理
    def post(self,request):
        username = request.POST.get('username')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        mobile = request.POST.get('mobile')
        allow = request.POST.get('allow')
        sms_code = request.POST.get('msg_code')


        if not all([username,password,password2,mobile,allow]):
            return HttpResponseForbidden("参数不齐")
        #判断用户名是否符合正则
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return HttpResponseForbidden("请输入5-20个字符的用户名")
        #判断密码是否符合
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return HttpResponseForbidden('请输入8-20位的密码')
        # 判断两次密码是否相同
        if password != password2:
            return HttpResponseForbidden('两次输入的密码不一致')
        # 判断手机号
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return HttpResponseForbidden('请输入正确的手机号码')
        # 判断是否勾选用户协议
        if allow != 'on':
            return HttpResponseForbidden('请勾选用户协议')
        # 判断短信验证码是否正确
        from django_redis import get_redis_connection
        redis_code_client = get_redis_connection("sms_code")
        redis_code = redis_code_client.get('sms_%s' % mobile)

        if redis_code is None:
            return render(request,"register.html",{'sms_code_errmsg':"无效的验证码"})
        if sms_code != redis_code.decode():
            return render(request,"register.html",{'sms_code_errmsg':'输入短信验证码有误'})



        # 判断完成后将数据写入数据库
        try:
            user = User.objects.create_user(username=username,password=password,mobile=mobile)
        except Exception as e:
            logger.error(e)
            return render(request,"register.html",{"register_message":"注册失败"})

        # 保持会话状态
        login(request,user)
        # 重定向到首页
        return redirect(reverse("contents:index"))

